package com.black.play.entity;

import com.black.play.component.SudokuWindow;
import com.black.play.config.AppConfig;
import com.black.play.constant.AppConstant;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 继承JPanel 用于定位所有节点对象
 *
 * @author ylx
 */
public class Grid extends JPanel
{
    private SudokuBoard board;
    private static final List<List<Cell>> GRIDS = new ArrayList<>();
    private static final List<Cell> ALL_CELLS = new ArrayList<>();
    public static final int LENGTH = AppConfig.getInt("window.length");
    public static final int NUMS = 9;
    // 匿名内部类加载配置
    public static final Dimension NODE_SIZE = new Dimension(20, 20)
    {
        {
            if (NUMS != 0)
            {
                this.width = LENGTH / NUMS;
                this.height = LENGTH / NUMS;
            }
        }
    };

    static
    {
        initGrid();
    }

    /**
     * 根据配置的宽高和行列数初始化网格
     * 生成全列表和二维网格列表
     */
    public static void initGrid()
    {
        for (int rowNum = 0; rowNum < NUMS; rowNum++)
        {
            List<Cell> row = new ArrayList<>();
            for (int colNum = 0; colNum < NUMS; colNum++)
            {
                Cell cell = new Cell(colNum * NODE_SIZE.width, rowNum * NODE_SIZE.height);
                row.add(cell);
                ALL_CELLS.add(cell);
            }
            GRIDS.add(row);
        }
    }

    /**
     * 实例化时构造必要参数
     */
    public Grid()
    {
        // 标准网格布局
        this.setLayout(new GridLayout(NUMS, NUMS));
        // 设置画板大小铺满窗口
        this.setPreferredSize(new Dimension(WIDTH, HEIGHT));
        this.setBackground(SudokuWindow.BACKGROUND);
        GRIDS.forEach(row -> row.forEach(this::add));
        // 允许键盘事件聚焦
        setFocusable(true);
        requestFocusInWindow();
    }

    /**
     * 开始游戏时的初始化内容
     */
    public void init()
    {
        initNumbers();
    }

    /**
     * 初始化数字
     */
    private void initNumbers()
    {
        board = SudokuGenerator.generateCompleteSudoku();
        int[][] numBoards = board.getBoard();
        int holes = AppConfig.getInt("grid.cell.holes");
        SudokuGenerator.removeNumbersFromBoard(numBoards, holes);
        if (holes > 64)
        {
            JOptionPane.showMessageDialog(this, AppConstant.ERROR_MSG, AppConstant.ERROR, JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        if (holes < 1)
        {
            JOptionPane.showMessageDialog(this, "就算再想通关也不用一个数字都不填吧!", AppConstant.ERROR, JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        for (int rowNum = 0; rowNum < NUMS; rowNum++)
        {
            List<Cell> row = GRIDS.get(rowNum);
            for (int colNum = 0; colNum < NUMS; colNum++)
            {
                Cell cell = row.get(colNum);
                cell.setValue(numBoards[rowNum][colNum]);
            }
        }
    }

    /**
     * 判断通关
     *
     * @return 是否通关
     */
    public boolean isSuccess()
    {
        return ALL_CELLS.stream().noneMatch(Cell::isEmpty);
    }

    public boolean isError(int x, int y, CellValue value)
    {
        int row = y / NODE_SIZE.height;
        int col = x / NODE_SIZE.width;
        int[][] boardValue = board.getBoard();
        int intValue = CellValue.indexOf(value);
        boardValue[row][col] = intValue;
        return !SudokuCreator.isValid(boardValue, row, col, intValue);
    }
}
